import { useEffect, useRef, useState } from 'react';
import { request } from 'umi';
import { Tree, message, Modal, Form, Input, Cascader, Button } from 'antd';
import { EditOutlined, DeleteOutlined } from '@ant-design/icons';
import styles from './index.less';

// 钩子（表单）
const { useForm } = Form;
interface IAreaItem {
  areaId: number;
  areaName: string;
  key: string;
  parentId: number;
  level: number;
  areas?: any;
  children?: IAreaItem[];
}
let originAreaList: IAreaItem[] = [];
const SysArea = () => {
  const [areaList, setAreaList] = useState<IAreaItem[]>([]);
  const [searchText, setSearchText] = useState('');
  const [expandedKeys, setExpandedKeys] = useState([]);
  const [searchAreaList, setSearchAreaList] = useState<IAreaItem[]>([]);
  const [showModal, setShowModal] = useState(false);
  const [showAddModal, setShowAddModal] = useState(false);
  const [currentArea, setCurrentArea] = useState<IAreaItem>({} as IAreaItem); // 获取当前数据 用于编辑
  const inputRef = useRef(null);
  const [form] = useForm();


  // 父级与子级，如果是父级，且父级的level属性小于子级的属性，就返回相应的父级
  // 如果找不到，就拿父级里面的 孩子 和 item 再照上面的方法对比 如果找到结果  返回相应的父级，如果实在找不到 
  // 有可能返回的是undefined。
  // 一级转多级
  function findParent(
    array: Array<IAreaItem>,
    item: IAreaItem,
  ): IAreaItem | undefined {
    for (let i = 0; i < array.length; i++) {
      if (array[i].areaId === item.parentId && array[i].level < item.level) {
        return array[i];
      }
      if (array[i].children) {
        let result = findParent(array[i].children!, item);
        if (result) {
          return result;
        }
      }
    }
  }
  // 这里直接调用 获取数据 没有使用dva 而且 useEffect 里面不能使用 async 和 await
  useEffect(() => {
    getAreaList();
  }, []);

  // 判断孩子里面有没有这个地址
  function hasSearchdAreaName(
    { children }: IAreaItem,
    searchText: string,
  ): boolean {

    // 如果没有孩子 返回false
    if (!children) return false;
    for (let i = 0; i < children!.length; i++) {
      if (children![i].areaName.indexOf(searchText) !== -1) {

        // 如果当前地区包含该字段返回true
        return true;
      }
      if (children![i].children) {

        // 如果地区的children属性存在 进行递归调用
        let result = hasSearchdAreaName(children![i], searchText);
        if (result) {
          return result;
        }
      }
    }

    // 如果以上条件都不符合 就返回false 
    return false;
  }

  // 搜索过滤 如果自身有 该搜索文本或者 孩子有该搜索文本的话，就返回该item
  function filterSearchdAreaName(
    children: IAreaItem[],
    searchText: string,
  ): IAreaItem[] {
    return children!
      .map((item) => {
        if (
          // 本身的areaName也是有这个搜索词
          // 孩子里面有这个搜索词
          item.areaName.indexOf(searchText) !== -1 ||
          hasSearchdAreaName(item, searchText)
        ) {

          // 如果有children继续递归
          if (item.children) {
            item.children = filterSearchdAreaName(
              item.children!,
              searchText,
            ) as IAreaItem[];
            return item;
          } else {
            return item;
          }
        } else {
          return undefined;
        }
      })
      .filter((item) => item) as IAreaItem[]; // 去掉空数组空字符串undefined null ,因为这里面会返回undefined
  }

  // 搜索框
  useEffect(() => {
    // 计算searchAreaList
    if (searchText) {
      let searchAreaList = filterSearchdAreaName(areaList, searchText);
      setSearchAreaList(searchAreaList);
    }
  }, [searchText]);

  // 获取keys
  function getKeys(array: IAreaItem[]): string[] {
    const keys: string[] = [];
    for (let i = 0; i < array.length; i++) {
      keys.push(array[i].key);
      if (array[i].children) {
        keys.push(...getKeys(array[i].children!));
      }
    }
    return keys;
  }

  useEffect(() => {
    if (searchAreaList.length && searchText) {
      setExpandedKeys(getKeys(searchAreaList) as never[]);
    }
  }, [searchAreaList, searchText]);

  // 获取数据的请求
  function getAreaList() {
    request('/admin/area/list').then((res) => {

      // 处理数据 划分省市区
      originAreaList = res;
      const areaList: IAreaItem[] = [];
      res.sort((a: any, b: any) => a.level - b.level);
      res.forEach((item: IAreaItem) => {
        item.key = String(item.areaId); // 这里添加了key字段
        let parent = findParent(areaList, item);
        if (parent) {

          // 如果有父级 给把子级放入父级中去
          parent.children = parent.children || [];
          parent.children.push(item);
        } else {

          // 如果没找到的话放在第一级
          areaList.push(item);
        }
      });
      setAreaList(areaList);
    });
  }

  // 删除
  async function deleteArea({ areaId }: IAreaItem) {
    try {
      await request(`/admin/area/${areaId}`, { method: 'DELETE' });
      message.success('删除成功');
      getAreaList(); // 删除以后更新页面
    } catch {
      message.error('删除失败');
    }
  }

  // 修改
  async function editArea() {
    let { editParentId } = form.getFieldsValue();  // 获取form当前修改完毕之后的值
    const { areaId, areaName, level } = currentArea;
    const parentId = editParentId.pop();
    let parentIndex = originAreaList.findIndex(item => item.areaId === parentId);
    const data = {
      areaId,
      areaName,
      area: null,
      level: originAreaList[parentIndex].level + 1,
      parentId
    }
    try {
      await request(`/admin/area`, { method: 'PUT', data });
      message.success('编辑成功');
      getAreaList();
      setShowModal(false);
    } catch {
      message.error('编辑失败');
    }
  }

  // 增加  
  async function addArea() {
    let { editParentId } = form.getFieldsValue();  // 获取form当前修改完毕之后的值
    const parentId = editParentId.pop();
    let parentIndex = originAreaList.findIndex(item => item.areaId === parentId);    
    const data = {
      areaId: 0,
      areaName:((inputRef.current as any).input as HTMLInputElement).value,
      area: null,
      level: originAreaList[parentIndex].level + 1,
      parentId
    }
    try {
      await request(`/admin/area`, { method: 'POST', data });
      message.success('增加成功');
      getAreaList();
      setShowAddModal(false);
    } catch {
      message.error('增加失败');
    }
  }
  return (
    <div className={styles.page}>
      <div>
        <p className={styles.searchAndAdd}>
          <Input
            type="text"
            className={styles.inputArea}
            value={searchText}
            onChange={(e) => setSearchText(e.target.value)}  // 受控组件
            placeholder='地区关键词'
          />
          <Button type="primary" onClick={() => {
            setShowAddModal(true);
          }}>新增</Button>
        </p>
        <Tree
          treeData={searchText ? searchAreaList : areaList}  // 放置数据  filename自定义节点
          // expandedKeys={expandedKeys}
          // 自定义渲染节点
          titleRender={(nodeData) => {
            return (
              <div className={styles.area}>
                <span>{nodeData.areaName}</span>
                <p className={styles.btns}>
                  <a
                    onClick={() => {
                      setCurrentArea(nodeData);
                      form.setFieldsValue(nodeData);
                      setShowModal(true);
                    }}
                  >
                    <EditOutlined />
                    <span>修改</span>
                  </a>
                  <a onClick={() => deleteArea(nodeData)}>
                    <DeleteOutlined />
                    <span>删除</span></a>
                </p>
              </div>
            );
          }}
        />
        {/* 在react diffe 中有三个重要的原则，diff算法时间复杂度一定是n的立方，dom节点的个数，react在此基础上做了三个假设，第一个假设通过type来判断，第二个不做跨级比较，第三个就是key的优化，只要currentArea改变之后key就一直在改变，只要改变，之前不存在，现在存在了，之前销毁，现在重新创建， */}
        {/* 为什么Modal重新创建 Form initialValue就生效了呢？ 这个initial用在Didmounted之前 ，这里key的目的就是强制组件的销毁创建，也可以使用form表单里面的动态修改set*/}
        <Modal
          key={JSON.stringify(currentArea)}
          title="修改"
          visible={showModal}
          onOk={editArea}
          onCancel={() => setShowModal(false)}
        >
          <Form initialValues={currentArea} form={form}>
            <Form.Item
              label="地区名称"
              name="areaName"
              rules={[{ required: true, message: '请输入地区名称!' }]}
            >
              <Input />
            </Form.Item>
            <Form.Item
              label="上级地区"
              name="editParentId"
              rules={[{ required: true, message: '请输入地区名称!' }]}
            >
              {/* 自定义 options 中 label value children 的字段 */}
              <Cascader fieldNames={{ label: 'areaName', value: 'areaId' }} options={areaList} placeholder="请选择" />
            </Form.Item>
          </Form>
        </Modal>

        <Modal
          key={JSON.stringify(currentArea)}
          title="新增"
          visible={showAddModal}
          onOk={addArea}
          onCancel={() => setShowAddModal(false)}
        >
          <Form form={form}>
            <Form.Item
              label="地区名称"
              name="areaName"
              rules={[{ required: true, message: '区域名称不能为空' }]}
            >
              <Input ref={inputRef}/>
            </Form.Item>
            <Form.Item
              label="上级地区"
              name="editParentId"
              rules={[{ required: true, message: '请输入地区名称!' }]}
            >
              {/* 自定义 options 中 label value children 的字段 */}
              <Cascader fieldNames={{ label: 'areaName', value: 'areaId' }} options={areaList} placeholder="请选择" />
            </Form.Item>
          </Form>
        </Modal>
      </div>
    </div>


  );
};

export default SysArea;
